{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 自然常数 e"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 简介"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "e，作为数学常数，是自然对数函数的底数。有时被称为欧拉数（Euler's number），以瑞士数学家欧拉命名；还有个较少见的名字纳皮尔常数，用来纪念苏格兰数学家约翰·纳皮尔引进对数。它是一个无限不循环小数，JavaScript 里，其近似值为 Math.E = 2.718281828459045"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "${\\displaystyle e=\\lim _{n\\to \\infty }\\left(1+{\\frac {1}{n}}\\right)^{n}}$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SymPy 实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sympy import *\n",
    "n = symbols('n')\n",
    "expr = (1 + 1/n) ** n\n",
    "\n",
    "e = limit(expr, n, oo)\n",
    "e.evalf()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## JS 实现"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```javascript\n",
    "const max = 1e11\n",
    "\n",
    "const e = (1 + 1 / max) ** max\n",
    "console.log(e)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意：由于理论上的定义，n 应当趋向于正无穷，但实际计算中，受 js 计算精度限制，max 取太大会有计算误差。自然底数 e 还有另一个无穷级数的定义：\n",
    "\n",
    "$e=\\frac{1}{0!} + \\frac{1}{1!} + \\frac{1}{2!} + \\frac{1}{3!} + \\cdots$\n",
    "\n",
    "根据这个，我们可以有限步地求前 N 项的和，我们需要用 js 实现一个阶乘"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```javascript\n",
    "const factorial = (n) => {\n",
    "  if (n < 2) return 1\n",
    "  return n * factorial(n - 1)\n",
    "}\n",
    "\n",
    "function getE() {\n",
    "  let ret = 0\n",
    "  const max = 20\n",
    "  for (let n = 0; n < max; n++) {\n",
    "    ret += 1 / factorial(n)\n",
    "  }\n",
    "  return ret\n",
    "}\n",
    "console.log(getE())\n",
    "2.7182818284590455\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到， 取前 20 位，工程上就足够可用了"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 应用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "自然底数 e 有很多实际用处。\n",
    "\n",
    "例：假设有 1000 个乒乓球，其中有一个是可以中奖的红球，那么抽 1000 次，中奖的概率是多少？\n",
    "\n",
    "解：这是一个从数量为 N 的样本中“有放回地”随机抽取出1个\"数量同样为N\"的样本。其计算公式为 $(1- \\frac{1}{n})^{n}$， 我们把 1000 - 10000 分别代进去，发现这个比值接近一个常数 0.36. 即你抽 1000 次，将有 360 次左右可以抽中红球。这个值与你直觉相符吗？\n",
    "通过前面的定义，我们可以推导出，这个极限值为 1/e, 即"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\displaystyle \\lim_{N\\rightarrow+\\infty}{(1-\\frac{1}{N})^{N}}\\rightarrow\\frac{1}{e}\\approx0.36$"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
